home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
apps
/
xconf
/
ConfRouter.c++
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
6KB
|
260 lines
// Conf includefile
#include "ConfRouter.h"
// unix includes
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <malloc.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <bstring.h>
#include <CC/osfcn.h>
#include <netdb.h>
#include <arpa/inet.h>
ConfRouter::ConfRouter() {}
ConfRouter::~ConfRouter() {}
void ConfRouter::Init(int port)
{
_port = port;
_addrSize = sizeof(struct sockaddr_in);
bzero(&_tcpSendAddr, _addrSize);
_tcpSendAddr.sin_family = AF_INET;
_tcpSendAddr.sin_port = htons(_port);
_tcpSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&_tcpRecvAddr, _addrSize);
_tcpRecvAddr.sin_family = AF_INET;
_tcpRecvAddr.sin_port = htons(_port);
_tcpRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&_udpSendAddr, _addrSize);
_udpSendAddr.sin_family = AF_INET;
_udpSendAddr.sin_port = htons(_port);
_udpSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&_udpRecvAddr, _addrSize);
_udpRecvAddr.sin_family = AF_INET;
_udpRecvAddr.sin_port = htons(_port);
_udpRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(!setupTCP()) {
printf("Error setting up TCP socket.\n");
exit(-1);
}
if(!setupUDP()){
printf("Error setting up UDP socket.\n");
exit(-1);
}
}
Boolean ConfRouter::setupTCP()
{
_tcpSocket = socket(AF_INET, SOCK_STREAM, 0);
if(_tcpSocket < 0) {
perror("socket");
return(FALSE);
}
if(bind(_tcpSocket, &_tcpRecvAddr, _addrSize) < 0) {
perror("bind");
return(FALSE);
}
if(listen(_tcpSocket, 5) < 0) {
perror("listen");
return(FALSE);
}
if(fcntl(_tcpSocket, F_SETFL, FASYNC) < 0) {
perror("fcntl");
return(FALSE);
}
if(fcntl(_tcpSocket, F_SETOWN, getpid()) < 0) {
perror("fcntl");
return(FALSE);
}
return(TRUE);
}
Boolean ConfRouter::setupUDP()
{
_udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
if(_udpSocket < 0) {
perror("socket");
return(FALSE);
}
int on = 1;
// doing this before the bind allows multiple bindings to this port
if(setsockopt(_udpSocket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
perror("setsockopt(SO_REUSEPORT)");
return(FALSE);
}
struct in_addr grpAddr;
grpAddr.s_addr = inet_addr(XCONF_MCAST_GROUP);
if(!IN_MULTICAST(grpAddr.s_addr)) {
fprintf(stderr, "Invalid multicast group address.\n");
return(FALSE);
}
// enable multicasting and limit # gateways packets will cross.
u_char ttl = MAX_MCAST_HOPS;
int sz = sizeof(ttl);
if(setsockopt(_udpSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sz) < 0) {
perror("setsockopt(IP_MULTICAST_TTL)");
return(FALSE);
}
_udpSendAddr.sin_addr = grpAddr;
struct ip_mreq mreq;
mreq.imr_multiaddr = grpAddr;
struct in_addr ifAddr;
ifAddr.s_addr = htonl(INADDR_ANY);
mreq.imr_interface = ifAddr;
sz = sizeof(mreq);
if(setsockopt(_udpSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sz) < 0) {
perror("setsockopt(IP_ADD_MEMBERSHIP)");
return(FALSE);
}
if(bind(_udpSocket, &_udpRecvAddr, _addrSize) < 0) {
perror("bind");
return(FALSE);
}
if(fcntl(_udpSocket, F_SETFL, FASYNC) < 0) {
perror("fcntl(F_SETFL)");
return(FALSE);
}
if(fcntl(_udpSocket, F_SETOWN, getpid()) < 0) {
perror("fcntl(F_SETOWN)");
return(FALSE);
}
return(TRUE);
}
Boolean ConfRouter::handleTCP()
{
struct Message msg;
struct sockaddr_in f;
int fromlen = sizeof(f);
if(recvfrom(_tcpSocket, &msg, sizeof(msg), 0, &f, &fromlen) < 0) {
perror("recv");
return(FALSE);
}
printf("read TCP message.\n");
int len = sizeof(msg) - sizeof(msg.data) + strlen(msg.data);
if(sendto(_udpSocket, &msg, len, 0, &_udpSendAddr, _addrSize) < 0) {
perror("send");
return(FALSE);
}
bzero(msg.data, sizeof(msg.data));
printf("sent UDP message.\n\n");
return(TRUE);
}
Boolean ConfRouter::handleUDP()
{
struct Message msg;
struct sockaddr_in f;
int fromlen = sizeof(f);
if(recvfrom(_udpSocket, &msg, sizeof(msg), 0, &f, &fromlen) < 0) {
perror("recvfrom");
return(FALSE);
}
printf("read UDP message.\n");
int len = sizeof(msg) - sizeof(msg.data) + strlen(msg.data);
if(send(_tcpSocket, &msg, len, 0) < 0) {
perror("sendto");
return(FALSE);
}
bzero(msg.data, sizeof(msg.data));
printf("sent TCP message.\n\n");
return(TRUE);
}
void ConfRouter::Run()
{
int newsock;
for(;;) {
newsock = accept(_tcpSocket, NULL, NULL);
printf("new connection\n");
if(!fork()) {
// child process
signal(SIGPOLL, SIG_IGN);
close(_tcpSocket);
_tcpSocket = newsock;
int nfds = _tcpSocket + 1;
fd_set readfds;
FD_ZERO(&readfds);
for(;;) {
FD_SET(_tcpSocket, &readfds);
FD_SET(_udpSocket, &readfds);
if(select(nfds, &readfds, (fd_set*)0, (fd_set*)0, (struct timeval*)0) < 0) {
perror("select");
exit(-1);
}
printf("select occured\n");
if(FD_ISSET(_tcpSocket, &readfds)) {
handleTCP();
}
if(FD_ISSET(_udpSocket, &readfds)) {
handleUDP();
}
}
}
else {
// parent process
close(newsock);
}
}
}
void ConfRouter::Quit()
{
close(_tcpSocket);
close(_udpSocket);
exit(1);
}